package com.mgm.controller.api;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import com.mgm.advertisement.service.AdvertisementService;
import com.mgm.affiliate.service.AffiliateService;
import com.mgm.affsettings.service.AffsettingsService;
import com.mgm.click.service.ClickInfoService;
import com.mgm.constant.GobalConstant;
import com.mgm.conversion.service.ConversionService;
import com.mgm.pojo.Advertisement;
import com.mgm.pojo.Affiliate;
import com.mgm.pojo.Affsettings;
import com.mgm.pojo.ClickInfo;
import com.mgm.pojo.ConversionInfo;
import com.mgm.utils.HttpConnectionUtil;
import com.mgm.utils.JodaTimeUtil;

/**
 * 提供给上游的转化接口
 * @ClassName: ConversionController 
 * @Description: 上游会调用该接口，
 * 发送成功转化数据给我们，我们会302继续发送给下游
 * @author Andy Zhang
 * @date 2018年8月30日 下午5:03:07
 * 二级域名：con.moboair.net  
 *
 */
@Controller
@RequestMapping("/api")
public class ConversionController {
	
	private static Logger logger =LoggerFactory.getLogger(ConversionController.class);
	
	@Autowired
	private ClickInfoService clickInfoService;
	@Autowired
	private ConversionService conversionService;
	@Autowired
	private AdvertisementService advertisementService;
	@Autowired
	private AffiliateService affiliateService;
	@Autowired
	private AffsettingsService affsettingsService;
	
	//Cheetah - http://con.moboair.net/?tid={transaction_id}&payout={payout}&pub_id={publisher_id}&sub_id={sub_id}&offerid={campaign_id}
	//mobpals - http://con.moboair.net/?tid={click id}&gaid={gaid}&idfa={idfa}&osv={os version}&sub_id={subid}&aff_sub1={aff_sub1}&aff_sub2={aff_sub2}
	//Clickdealer - http://con.moboair.net/?tid=​[clickid]​&payout=​[payout]​&aid=​[device_id]​&idfa=​[idfa]​&gaid=​[gaid]​&sub_id=​[data1]
	//Applift - http://con.moboair.net/?tid=​​{aff_click_id}&payout=​{payout}​&aid=​{source}​&idfa=​{ios_ifa}&gaid=​{unid}
	@RequestMapping(value="/v1/callback", method = RequestMethod.GET)
	public void receiveClick(
			@RequestParam(value="tid", required=true) String tid, 
			@RequestParam(value="payout", required=false) String payout, 
			@RequestParam(value="pub_id", required=false) String publiserid,
			@RequestParam(value="sub_id", required=false) String affSub, 
			@RequestParam(value="offerid", required=false) String offerid, 
			@RequestParam(value="idfa", required=false) String idfa, @RequestParam(value="gaid", required=false) String gaid, @RequestParam(value="aid", required=false) String aid,
			HttpServletRequest request, HttpServletResponse response) {
		logger.info("【回传转化】 Track URL:{}", request.getRequestURL() + "?" + request.getQueryString());
		List<ConversionInfo> isExistCon = conversionService.findByTid(tid);
		if(!CollectionUtils.isEmpty(isExistCon)) return; //防止上游重复调用
		
		ClickInfo clickInfo = clickInfoService.findByTid(tid); //根据tid获取Click信息
		ConversionInfo con = new ConversionInfo();
		con.setConversionat(new Date());
		con.setTid(tid);
		con.setPayPrice(StringUtils.isEmpty(payout) ? clickInfo.getPayPrice() : new BigDecimal(payout));
		con.setSubaffid(StringUtils.isEmpty(affSub) ? clickInfo.getAffid() : affSub);
		
		checkConversion(con, clickInfo);
		
		int i = conversionService.save(con); //con入库
		logger.info("【Con 入库】 Conversion obj :{}", con.toString());
		
		if (!con.getCode().equals("0")) return; 
		
		long count = conversionService.countByCode(con.getOfferid(), con.getAffid(), GobalConstant.CONVERSION_SUCCESS+""); //成功数量
		Affiliate affiliate = affiliateService.findByAffId(con.getAffid()); //获取渠道信息
		//判断shave
		boolean isPostback = true;
		if(affiliate.getShave() > 0) {
			long n = count * affiliate.getShave() % GobalConstant.PERCENT;
			if (n == 0) isPostback = false; 
		}
		
		if(isPostback) {
			//发送con给渠道
			String postbackUrl = replaceUrl(affiliate.getPostBack(), clickInfo);
			logger.info("【回传渠道con的路径】 Aff postback url is :{}", postbackUrl);
			String postbackRes = HttpConnectionUtil.doGet(postbackUrl); //postback url
			logger.info("【Con Post back Result】 Aff postback return result :{}", postbackRes);
			con.setP2("send:$" + postbackRes + "$"); //更新数据库已回调
			conversionService.update(con);
		}
		
		
	}
	
	/**
	 * CONVERSION_SUCCESS = 0; //正常conversion 
	 * CONVERSION_OFFER_CLOSE = 1; //offer为关
	 * CONVERSION_SHAVE = 2; //shave 
	 * CONVERSION_OVER_24H = 3; //超过24h
	 * CONVERSION_LACK_DEVICE = 4; //缺少设备信息 
	 * CONVERSION_ATTAIN_CAP = 5; //达到cap
	 * CONVERSION_LIMIT_30S = 6; //距离click小于30秒
	 */
	private void checkConversion(ConversionInfo con, ClickInfo clickInfo) {
		
		Advertisement ad = advertisementService.findByOfferId(clickInfo.getOfferid()); //获取offer
//		Advertiser ader = advertiserService.selectById(ad.getAdv_id());
		BigDecimal totalCap = conversionService.selectTotalCap(clickInfo.getOfferid()); //获取总cap
		BigDecimal dailyCap = conversionService.selectDailyCap(clickInfo.getOfferid()); //获取日cap
		Affsettings affsettings = affsettingsService.selectByAffIdAndAdmentId(clickInfo.getAffid(), clickInfo.getOfferid());
		
		if(ad.getEnabled() == false) { //offer是否关闭
			con.setCode(GobalConstant.CONVERSION_OFFER_CLOSE+"");
		} else if (JodaTimeUtil.diffSecond(clickInfo.getClickat(), con.getConversionat()) < 30) { //距离click小于30秒
			con.setCode(GobalConstant.CONVERSION_LIMIT_30S+"");
		} else if (JodaTimeUtil.diffHour(clickInfo.getClickat(), con.getConversionat()) > 24) { //距click发送时间超过24h
			con.setCode(GobalConstant.CONVERSION_OVER_24H+"");
		} else if (!StringUtils.isEmpty(ad.getRequires())) { //转化需要deviceid且下游click参数中没有  (idfa/gaid/aid)
			if("aid".equals(ad.getRequires()) && StringUtils.isEmpty(clickInfo.getAid())) {
				con.setCode(GobalConstant.CONVERSION_LACK_DEVICE+"");
			} else if("gaid".equals(ad.getRequires()) && StringUtils.isEmpty(clickInfo.getGaid())) {
				con.setCode(GobalConstant.CONVERSION_LACK_DEVICE+"");
			} else if("idfa".equals(ad.getRequires()) && StringUtils.isEmpty(clickInfo.getIdfa())) {
				con.setCode(GobalConstant.CONVERSION_LACK_DEVICE+"");
			}
		} else if (ad.getPayout_cap() != null && totalCap.compareTo(ad.getPayout_cap()) > 0) { //offer已达总cap（offer那边cap是否限制&计算真正转化的cap）
			con.setCode(GobalConstant.CONVERSION_ATTAIN_CAP+"");
		} else if (ad.getDaily_payout_cap() != null && dailyCap.compareTo(ad.getDaily_payout_cap()) > 0) { //offer已达日总cap
			con.setCode(GobalConstant.CONVERSION_ATTAIN_CAP+"");
		} else if (affsettings.getTotalCap() != null || affsettings.getDailyCap() != null) { //offer-渠道 cap判断
			//判断 Offer-渠道 cap
			BigDecimal affTotalCap = conversionService.selectTotalCapByAffId(clickInfo.getOfferid(), clickInfo.getAffid());
			BigDecimal affDailyCap = conversionService.selectDailyCapByAffId(clickInfo.getOfferid(), clickInfo.getAffid());
			if(affsettings.getTotalCap() != null && affTotalCap.compareTo(affsettings.getTotalCap()) > 0) { //Offer-渠道已达总cap
				con.setCode(GobalConstant.CONVERSION_ATTAIN_CAP+"");
			} else if (affsettings.getDailyCap() != null && affDailyCap.compareTo(affsettings.getDailyCap()) > 0) { //Offer-渠道已达日cap
				con.setCode(GobalConstant.CONVERSION_ATTAIN_CAP+"");
			}
		} else { 
			con.setCode(GobalConstant.CONVERSION_SUCCESS+""); //成功状态
		}
		
		con.setOfferid(clickInfo.getOfferid());
		con.setOffername(clickInfo.getOffername());
		con.setAffid(clickInfo.getAffid());
		con.setPkgname(clickInfo.getPkgname());
		con.setAfftid(clickInfo.getAfftid()); //这存渠道tid, tid存的是MGM tid
		con.setPayType(clickInfo.getPayType());
		con.setAffPayout(clickInfo.getAffPayout());
		
		con.setIp(clickInfo.getIp());
		con.setRefer(clickInfo.getRefer());
		con.setUserAngent(clickInfo.getUserAngent());
		
		con.setIdfa(clickInfo.getIdfa());
		con.setGaid(clickInfo.getGaid());
		con.setAid(clickInfo.getAid());
		
		con.setP1(clickInfo.getP1());
		con.setP2(clickInfo.getP2());
		con.setP3(clickInfo.getP3());
		con.setP4(clickInfo.getP4());
	}
	
	private String replaceUrl(String url, ClickInfo clickInfo) {
		//infomobi: http://api.infomobi.me/api/s2s/postback?clickid={tid}&affiliate_id={subaffid}&payout={payout} 
		Map<String, String> map = new HashMap<>();
		map.put("{transactionid}", clickInfo.getAfftid()); //渠道当时click过来的tid
		map.put("{offid}", clickInfo.getOfferid()); //offerid
		map.put("{subaffid}", clickInfo.getSubaffid());
		map.put("{payout}", clickInfo.getAffPayout()==null ? clickInfo.getPayPrice().toString() : clickInfo.getAffPayout().toString()); //给下游单价(溢价后价格)
		map.put("{pkgname}", StringUtils.isEmpty(clickInfo.getPkgname()) ? "" : clickInfo.getPkgname());
		map.put("{idfa}", StringUtils.isEmpty(clickInfo.getIdfa()) ? "" : clickInfo.getIdfa()); 
		map.put("{gaid}", StringUtils.isEmpty(clickInfo.getGaid()) ? "" : clickInfo.getGaid());
		map.put("{aid}", StringUtils.isEmpty(clickInfo.getAid()) ? "" : clickInfo.getAid());
		
		map.put("{data1}", StringUtils.isEmpty(clickInfo.getD1()) ? "" : clickInfo.getD1());
		map.put("{data2}", StringUtils.isEmpty(clickInfo.getD2()) ? "" : clickInfo.getD2());
		map.put("{data3}", StringUtils.isEmpty(clickInfo.getD3()) ? "" : clickInfo.getD3());
		map.put("{data4}", StringUtils.isEmpty(clickInfo.getD4()) ? "" : clickInfo.getD4());
		for (String key : map.keySet()) {
			url = url.replace(key, map.get(key)==null ? "" : map.get(key));
		}
		
		return url;
	}
	
}
